#include <stdio.h> 
#include <errno.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdlib.h>
#include <string.h>
#include <linux/fs.h> 

/*
 * read mmc test
 *
 * run command:
 *     ./read-mmc "/dev/mmcblk0" 0
 */

//extern int errno; 

int get_disk_sector(int fd){ 
  int sectorsize; 

  ioctl(fd, BLKSSZGET, &sectorsize) ; 

  return sectorsize; 
} 
/** 
 * read_disk_sector: 
 * @dev: raw disk FILE * 
 * @sector: 
 * return is the disk sectorsize 
 * */ 
int read_disk_sector(int fd, unsigned long sector, char **p){ 
  int sectorsize; 
  FILE *fp; 

  /* get disk sector size */ 
  sectorsize = get_disk_sector(fd); 
  if (sectorsize == 0){ 
    fprintf(stderr, "get disk sector size failed\n"); 
    return (-1); 
  } 

  /* seek it */ 
  lseek(fd, 0 ,SEEK_SET);

  //注，在offset设置得过大时，lseek可能返回OVERFLOW的错误，但实际上，它已经执行了定位，只是返回的值超出了范围。返回值为-1时，此时要判断一下错误号
  if (lseek(fd, (sectorsize * sector), SEEK_CUR) == -1 ){ 
    fprintf(stderr, "seek to %ld failed\n", sectorsize * sector); 
    return (-1); 
  } 
  /* read it */ 
  *p = (char *)malloc(sectorsize); 
  if (*p == NULL){ 
    fprintf(stderr, "malloc memory failed\n"); 
    return (-1); 
  } 

  return read(fd, *p, sectorsize); 
} 
/* dump data for display */ 
void dump_disk_sector(char *p, int size){ 
  int i; 
  for (i = 0; i< size; i++){ 
    if (i % 16 == 0 && i != 0) 
      printf("\n"); 
    printf("0x%02x,", (unsigned int )*p++ & 0xff); 
  } 

  printf("\n"); 
  return ; 
} 

int main(int argc, char **argv){ 
  char *d; 
  int size, sector_num; 
  int fd; 
  char dev[50] = "/dev/block/mmcblk0"; 

  printf("enter read mmcblk0 sector:\n");
  if(argc != 3)
    printf("error num of arg!\n");
  else{
    strcpy(dev, argv[1]);
    sscanf(argv[2], "%d", &sector_num);
    printf("read sector_num:%d\n", sector_num);
  }
  /* open it */ 
  fd = open(dev, O_RDONLY); 
  if (fd == -1){ 
    //fprintf(stderr, "open %s failed %s\n", dev, strerror(errno)); 
    return (-1); 
  } 

  size = read_disk_sector(fd, sector_num, &d); 
  printf("sector size:%d\n", size);
  close(fd); 

  if (size <= 0) return (0); 

  dump_disk_sector(d, size); 

  free(d); 

  return (0); 
}

